/*
 * Copyright 2009 Upskill.com.br
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.upskill.opensource.persistence;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * This class uses reflection to store objects in a text file. It's used to 
 * show an example of reflection and object persistence  
 *  
 * @author Rodrigo Prestes Machado
 * @version Set. 9, 2009
 */
public class Persistence {

	private String fileName;
	
	/**
	 * Constructor
	 * 
	 * @param String fileName : A file name
	 */
	public Persistence(String fileName){
		this.fileName = fileName;
	}
	
	/**
	 * Save the object state in a text file
	 * 
	 * @param Object object : An object
	 */
	@SuppressWarnings("unchecked")
	public void save(Object object){
		try {
			BufferedWriter bw = new BufferedWriter(new FileWriter(fileName, true));
			
			Class objClass = object.getClass();
			
			Field[] fields = objClass.getDeclaredFields();
			for (Field field : fields) {
				String methodName = getMethodName("get", field.getName());
				
				Method method = objClass.getMethod(methodName);

				String result = (String) method.invoke(object);
				if ( result != null){
					bw.write(field.getName() + ":" + result);
					bw.newLine();
				}	
			}
			bw.write("#");
			bw.newLine();
			bw.close();
		} 
		catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Retrieve objects from text file
	 * 
	 * @param Class objClass : An object that represents the class. The class 
	 * indicates the type of objects that will be stored inside the array 
	 * 
	 * @return ArrayList : Returns an array of objects
	 */
	@SuppressWarnings("unchecked")
	public List retrieve(Class objClass){
		try {
			Object object = null;
			ArrayList array = new ArrayList();
			
			BufferedReader br = new BufferedReader(new FileReader(fileName));
			
			String line = null;
			object = objClass.newInstance();
			while (( line = br.readLine()) != null){
				if (!line.equals("#")){
					String[] peaces = line.split(":");
					
					String key = peaces[0];
					String value = peaces[1];
					
					String methodName = getMethodName("set", key);
					Method method = objClass.getMethod(methodName, String.class);
					method.invoke(object, (String) value);
				}
				else{
					array.add(object);
					object = objClass.newInstance();
				}	
		    }
			br.close();
			return array;
		} 
		catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * Creates a method name
	 * 
	 * @param String prefix : The prefix of a method (get, set, etc.)
	 * @param String name   : The name of a method
	 * 
	 * @return String       : A method name
	 */
	private String getMethodName(String prefix, String name) {
		/** Criando o nome dos metodos **/
		String methodName = prefix
				+ name.substring(0, 1).toUpperCase()
				+ name.substring(1, name.length());
		return methodName;
	}
}